package com.java.basis.thread.n8;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;

/**
 * 任务拆分 ForkJoin
 *
 * @author wangning
 * @create 2022-02-11 15:06
 */
@Slf4j(topic = "c.TestForkJoin2")
public class TestForkJoin2 {
	public static void main(String[] args) {
		ForkJoinPool pool = new ForkJoinPool();
		System.out.println(pool.invoke(new MyTask(5)));

		//任务拆分，类似于递归
		//new MyTask(5) -> 5+new MyTask(4) -> 4+new MyTask(3) -> 3+new MyTask(2) -> 2+new MyTask(1)

	}

}

//1-n之间数字的和
@Slf4j(topic = "c.MyTask")
class MyTask extends RecursiveTask<Integer> {
	private static final long serialVersionUID = 5058345350804691477L;
	private final int n;

	public MyTask(int n) {
		this.n = n;
	}

	@Override
	protected Integer compute() {
		if (n == 1) {
			log.debug("join() {}", n);
			return 1;
		}
		MyTask myTask = new MyTask(n - 1);
		myTask.fork();//让一个线程去执行此任务
		log.debug("fork() {} + {}", n, myTask);
		int result = n + myTask.join();
		log.debug("join() {} + {} = {}", n, myTask, result);
		return result;
	}

	@Override
	public String toString() {
		return "{" + n + "}";
	}
}

@Slf4j(topic = "c.AddTask3")
class AddTask3 extends RecursiveTask<Integer> {

	private static final long serialVersionUID = 7355887279879008559L;

	int begin;
	int end;

	public AddTask3(int begin, int end) {
		this.begin = begin;
		this.end = end;
	}

	@Override
	public String toString() {
		return "AddTask3{" +
				"begin=" + begin +
				", end=" + end +
				'}';
	}

	@Override
	protected Integer compute() {
		if (begin == end) {
			log.debug("join() {}", begin);
			return begin;
		}
		if (end - begin == 1) {
			log.debug("join() {} + {} = {}", begin, end, end + begin);
			return end + begin;
		}
		int mid = (end + begin) / 2;
		AddTask3 t1 = new AddTask3(begin, mid);

		t1.fork();
		AddTask3 t2 = new AddTask3(mid + 1, end);
		t2.fork();
		log.debug("fork() {} + {} = ?", t1, t2);
		int result = t1.join() + t2.join();
		log.debug("join() {} + {} = {}", t1, t2, result);

		return result;
	}
}
